#ifndef __MOOSE_JSON_HH_
#define __MOOSE_JSON_HH_

#include <stdint.h>
#include <stdbool.h>

#include <moose_list.h>

typedef enum {
    e_moose_json_type_unknow = 0,
    e_moose_json_type_str,
    e_moose_json_type_bool,
    e_moose_json_type_int,
    e_moose_json_type_arr,
    e_moose_json_type_object,
    e_moose_json_type_json
}moose_json_type;

/* Define key/value struct */
typedef struct moose_json_key {
    moose_json_type type;
    union {
        char*   key_str;
        bool    key_bool;
        int64_t key_int;
    };
}moose_json_key;
typedef struct moose_json_value {
    moose_json_type type;

    union {
        char*   value_str;
        bool    value_bool;
        int64_t value_int;

        moose_list* list; /* moost_json_object */
    };
}moose_json_value;
/* End Define key/value struct */

/* Define moose_json_object struct */
typedef struct moose_json_object {
    moose_json_key key;
    moose_json_value value;
}moose_json_object;

typedef struct moose_json {
    moose_list* list; /* moost_json_object */
}moose_json;
/* End Define moose_json object struct */

/* Define external interface */

/**
 * Create moose_json object with str, return NULL if it occur error.
 * If str is NULL, Create empty moose_json object.
 *
 */
moose_json* moose_json_malloc(const char* str, unsigned int len);

/**
 * Release moose_json
 */
void moose_json_free(moose_json* moose_json_ptr);

/**
 * Put a object to moose_json
 */
moose_list* moose_json_put(moose_list* moose_json_ptr, moose_json_key* key, moose_json_value* value);

/**
 * Get a object from moose_json
 */
moose_json_value* moose_json_get(moose_list* moose_json_ptr, moose_json_key* key);

/**
 * Print Moose Json
 */
moose_json* moose_json_print(moose_json* moose_json_ptr);

/**
 * Serialize Moose Json
 */
moose_json* moose_json_serialize(moose_json* moose_json_ptr, char** str);

/**
 * For each json
 */
// typedef moose_json_object* (*fn_moose_json_foreach)(moose_json_object*, void* arg);
// moose_list* moose_json_foreach(moose_list* moose_list_ptr, fn_moose_json_foreach func, void* arg);
/* Foreach of list */
#define MOOSE_JSON_FOREACH(l, f, a)             \
    do {                                        \
        moose_list* ll = l;                     \
        while (ll != NULL)                      \
        {                                       \
            moose_list* l_tmp = ll->next;       \
            f(ll, a); \
            ll = l_tmp;                         \
        }                                       \
    }while(0)


/* End Define external interface */

#endif
